package com.feather.common.data.simple;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.feather.common.converter.FieldAssignmentHelper;
import com.feather.common.data.Column;
import com.feather.common.data.ColumnCollection;
import com.feather.common.data.DataColumn;
import com.feather.common.data.DataItemType;
import com.feather.common.data.DataRow;
import com.feather.common.data.DataRowCollection;
import com.feather.common.data.DataTable;

/**
 * @author flogyin
 */
public class SimpleDataTable implements DataTable, java.io.Serializable {
	private static final long	serialVersionUID	= 1L;

	protected String			catalog;
	protected String			schema;
	protected String			name;
	protected String			type;
	protected String			remarks;

	protected ColumnCollection	columns;
	protected DataRowCollection	rows;

	public SimpleDataTable() {
		this.columns = new SimpleColumnCollection();
		this.rows = new SimpleDataRowCollection();
	}

	public SimpleDataTable(ColumnCollection columns, DataRowCollection rows) {
		this.columns = columns;
		this.rows = rows;
	}

	@Override
	public DataItemType getItemType() {
		return DataItemType.DataTableItem;
	}

	@Override
	public String getCatalog() {
		return this.catalog;
	}

	@Override
	public void setCatalog(String catalog) {
		this.catalog = catalog;
	}

	@Override
	public String getSchema() {
		return this.schema;
	}

	@Override
	public void setSchema(String schema) {
		this.schema = schema;
	}

	@Override
	public String getName() {
		return this.name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String getType() {
		return this.type;
	}

	@Override
	public void setType(String type) {
		this.type = type;
	}

	@Override
	public String getRemarks() {
		return this.remarks;
	}

	@Override
	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}

	@Override
	public ColumnCollection getColumns() {
		return this.columns;
	}

	@Override
	public DataRowCollection getRows() {
		return this.rows;
	}

	@Override
	public void Clear() {
		this.columns.clear();
		this.rows.clear();
	}

	public DataTable copy() {
		return null;
	}

	@Override
	public DataRow newRow() {
		SimpleDataRow dataRow = new SimpleDataRow();
		int count = this.columns.getCount();
		for (int i = 0; i < count; i++) {
			Column column = this.columns.get(i);
			dataRow.add(new SimpleDataColumn(column));
		}
		getRows().add(dataRow);
		return dataRow;
	}

	@Override
	public Object toObject(@SuppressWarnings("rawtypes") Class cls, FieldAssignmentHelper helper) throws Exception {
		@SuppressWarnings("rawtypes")
		List list = toList(cls, helper);
		return list.size() > 0 ? list.get(0) : null;
	}

	@Override
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<Object> toList(Class cls, FieldAssignmentHelper helper) throws Exception {
		ArrayList list = new ArrayList();
		if (cls != null) {
			Field[] fields = cls.getDeclaredFields();
			if (fields != null) {
				ColumnCollection columns = getColumns();
				int columnsCount = columns.getCount();
				DataRowCollection rows = getRows();
				int rowCount = rows.getCount();
				for (int r = 0; r < rowCount; r++) {
					Object obj = cls.newInstance();
					list.add(obj);
					for (int f = 0; f < fields.length; f++) {
						if (Modifier.isFinal(fields[f].getModifiers())) {
							continue;
						}
						fields[f].setAccessible(true);
						String fieldName = fields[f].getName();
						for (int c = 0; c < columnsCount; c++) {
							String columnName = columns.get(c).getName();
							if (fieldName.equalsIgnoreCase(columnName)) {
								DataRow row = rows.get(r);
								DataColumn dataColumn = row.get(c);
								Object value = dataColumn.getObject();
								helper.assign(value, obj, fields[f]);
								break;
							}
						}
					}
				}
			}
		}
		return list;
	}

	@Override
	public Object[] toArray(@SuppressWarnings("rawtypes") Class cls, FieldAssignmentHelper helper) throws Exception {
		@SuppressWarnings("rawtypes")
		List list = toList(cls, helper);
		return list.toArray();
	}

	@Override
	public List<Map<String, ?>> toMap() {
		return this.rows.toMap();
	}

	@Override
	public String toJson() {
		/*
		 * StringBuilder builder = new StringBuilder(); String table =
		 * getName(); if (table == null) { table = "DataTable"; }
		 * builder.append("{\""); builder.append(table); builder.append("\":");
		 * 
		 * DataRowCollection dataRowCollection = getRows(); int rowsCount =
		 * dataRowCollection.getCount(); if (rowsCount > 0) {
		 * builder.append("["); for (int r = 0; r < rowsCount; r++) { if (r > 0)
		 * { builder.append(","); } DataRow dataRow = dataRowCollection.get(r);
		 * builder.append(dataRow.toJson()); } builder.append("]"); } else {
		 * builder.append("null"); }
		 * 
		 * builder.append("}"); return builder.toString();
		 */
		return this.rows.toJson();
	}

	/*
	 * public String toJson_rich() { ArrayList<String> columnList = new
	 * ArrayList<String>(); ColumnCollection columns = getColumns(); int
	 * columnCount = columns.getCount(); for (int c = 0; c < columnCount; c++) {
	 * String name = columns.get(c).getName(); columnList.add(name); }
	 * 
	 * ArrayList<LinkedHashMap<String,String>> rowList = new
	 * ArrayList<LinkedHashMap<String,String>>(); DataRowCollection rows =
	 * getRows(); int rowsCount = rows.getCount(); for (int r = 0; r <
	 * rowsCount; r++) { LinkedHashMap<String,String> rowMap = new
	 * LinkedHashMap<String,String>(); rowList.add(rowMap); DataRow row =
	 * rows.get(r); int colCount = row.getCount(); for (int c = 0; c < colCount;
	 * c++) { DataColumn dataColumn = row.get(c); String name =
	 * dataColumn.getColumn().getName(); String value = dataColumn.asString();
	 * rowMap.put(name, value); } }
	 * 
	 * LinkedHashMap<String,ArrayList> jsonMap = new
	 * LinkedHashMap<String,ArrayList>(); jsonMap.put("columns", columnList);
	 * jsonMap.put("rows", rowList); return JSON.toJSONString(jsonMap); }
	 */
	@Override
	public String toXml() {
		StringBuilder builder = new StringBuilder();
		String table = this.name;
		if (table == null) {
			table = "null";
		}
		builder.append("<");
		builder.append(table);
		builder.append(">");

		DataRowCollection dataRowCollection = getRows();
		int rowsCount = dataRowCollection.getCount();
		for (int r = 0; r < rowsCount; r++) {
			DataRow dataRow = dataRowCollection.get(r);
			builder.append("<row>");
			int columnCount = dataRow.getCount();
			for (int c = 0; c < columnCount; c++) {
				DataColumn dataColumn = dataRow.get(c);
				String name = dataColumn.getColumn().getName();
				String value = dataColumn.getString();
				builder.append("<");
				builder.append(name);
				builder.append(">");
				builder.append(value);
				builder.append("</");
				builder.append(name);
				builder.append(">");
			}
			builder.append("</row>");
		}

		builder.append("</");
		builder.append(table);
		builder.append(">");
		return builder.toString();
	}
}
